package cn.tedu.charging.order.service;

import cn.tedu.charging.common.pojo.message.DelayCheckMessage;
import cn.tedu.charging.common.pojo.po.ChargingBillFailPO;
import cn.tedu.charging.common.protocol.WebSocketMessage;
import cn.tedu.charging.order.endpoint.WebSocketServer;
import cn.tedu.charging.order.feign.DeviceClient;
import cn.tedu.charging.order.mapper.BillFailMapper;
import cn.tedu.charging.order.mapper.BillSuccessMapper;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class AmqpConsumerServiceImpl implements AmqpConsumerService{
    @Autowired
    private DeviceClient deviceClient;
    @Autowired
    private BillFailMapper billFailMapper;
    @Autowired
    private BillSuccessMapper billSuccessMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private WebSocketServer webSocketServer;
    //处理延迟消息的业务逻辑
    @Override
    public boolean handleDelayMessage(DelayCheckMessage delayMsg) {
        //1.抢锁 setnx key value key:{orderNo} EX 5
        String lockKey="charging:order:lock:"+delayMsg.getOrderNo();
        Boolean haveLock = redisTemplate.opsForValue().setIfAbsent(lockKey, "",5, TimeUnit.SECONDS);
        //2.判断抢锁结果
        if (!haveLock){
            log.debug("抢锁失败,业务结束,由其他业务处理当前订单");
            return true;
        }
        //3.根据抢锁成功调用业务
        try{
            this.doHandle(delayMsg);
        }catch (Exception e){
            log.error("执行消费订单延迟异常",e);
        }finally {
            //4.释放锁
            redisTemplate.delete(lockKey);
        }
        return true;
    }

    public boolean doHandle(DelayCheckMessage delayMsg) {
        //1.解析消息中orderNo billId 查询success或者fail有没有数据
        boolean exists=checkBillExists(delayMsg.getOrderNo());
        //2.判断
        if(!exists){
            //3.存储一个失败订单 saveFailBill
            saveFailBill(
                    delayMsg.getOrderNo(),
                    delayMsg.getUserId(),
                    delayMsg.getPileId(),
                    delayMsg.getGunId(),
                    "设备无响应");
            //4.通知用户换枪
            //推送消息给用户 通知换枪
            WebSocketMessage webSocketMessage=new WebSocketMessage();
            webSocketMessage.setState(1);//状态不同 前端处理逻辑不一样
            webSocketMessage.setMessage("不ok");
            webSocketMessage.setData("A设备启动失败,订单无法创建,请换枪,对不起,送您一张优惠券");
            webSocketServer.sendMsg2User(delayMsg.getUserId(), JSON.toJSONString(webSocketMessage));
            //5.http的openFeign调用DeviceClient
            deviceClient.updateGunStatus(delayMsg.getGunId(),3);
        }
        return true;
    }
    private void saveFailBill(String orderNo, Integer userId, Integer pileId, Integer gunId, String desc) {
        //组织一个po 写入fail表格
        ChargingBillFailPO po=new ChargingBillFailPO();
        po.setBillId(orderNo);
        po.setUserId(userId);
        po.setGunId(gunId);
        po.setFailDesc(desc);
        //当前业务需要的数据属性有则set 没有则单独查询 比如使用gunId查询stationId operatorId
        //使用userId 查询该用户类型 登记 绑定车辆
        log.debug("用户扫码下单启动失败,新增失败订单:{}",po);
        billFailMapper.insert(po);
    }

    private boolean checkBillExists(String orderNo) {
        QueryWrapper queryWrapper=new QueryWrapper();
        queryWrapper.eq("bill_id",orderNo);
        //1.select count(1) from success where bill_id=? successCount
        Long sucCount = billSuccessMapper.selectCount(queryWrapper);
        //2.select count(1) from fail where bill_id=? failCount
        Long failCount = billFailMapper.selectCount(queryWrapper);
        return failCount>0||sucCount>0;
    }
}
